#ifndef _COM_FUNC_HPP_
#define _COM_FUNC_HPP_

#include <dlcom/unknown.h>

#define MAX_PROGIDLEN		100
#define MAX_CONTAINERLEN	100

#define 	DllGetClassObjectFuncName	"DllGetClassObject"
typedef	HRESULT(OS_STDCALL	*DefineDllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID* ppv);

#define	DllGetAtFuncName			"DllGetAt"
typedef	CLSID(OS_STDCALL	*DefineDllGetAt)(LONG nIndex);

#define	DllGetCountFuncName		"DllGetCount"
typedef	LONG(OS_STDCALL		*DefineDllGetCount)();

#define 	DllProgIDFromCLSIDFuncName	"DllProgIDFromCLSID"
typedef	LPCSTR(OS_STDCALL	*DefineDllProgIDFromCLSID)(REFCLSID clsid);

#define 	DllCanUnloadNowFuncName		"DllCanUnloadNow"
typedef 	HRESULT(OS_STDCALL	*DefineDllCanUnloadNow)(void);

#define 	DllRegisterServerFuncName	"DllRegisterServer"
typedef	HRESULT(OS_STDCALL	*DefineDllRegisterServer)(void);

#define 	DllUnregisterServerFuncName	"DllUnregisterServer"
typedef	HRESULT(OS_STDCALL	*DefineDllUnregisterServer)(void);

#define 	DllStartServerFuncName		"DllStartServer"
typedef	HRESULT(OS_STDCALL	*DefineDllStartServer)(void);

#define 	DllStopServerFuncName		"DllStopServer"
typedef	HRESULT(OS_STDCALL	*DefineDllStopServer)(void);

#define NULLFuncName				"null"

uvStdComNameSpaceBegin

	class CUnknownImp
	{
	public:
		//volatile ULONG m_Ref;
		_atomic_t m_Ref;
		CUnknownImp() 
		{
            m_Ref.value = 0;
		}
		virtual ~CUnknownImp()
		{
            m_Ref.value = 0;
		}
	};

uvStdComNameSpaceEnd
	
#define  BEGIN_STDCOM_MAP \
	std_method(QueryInterface)(REFIID riid, void **ppv)	{	\


#define STDCOM_INTERFACE_ENTRY_UNKNOWN	\
	if(IID_IBase == riid)	\
	{	\
	*ppv = static_cast<IBase*>(this);	\
	this->AddRef();	\
	return S_OK;	\
	}	\

#define STDCOM_INTERFACE_ENTRY_UNKNOWN_(icast)	\
	if(IID_IBase == riid)	\
	{	\
	*ppv = static_cast<IBase*>(static_cast<icast*>(this));	\
	this->AddRef();	\
	return S_OK;	\
	}	\

#define STDCOM_INTERFACE_ENTRY(iface)	\
	if(_uuidof(iface) == riid)	\
	{	\
	*ppv = static_cast<iface*>(this);	\
	this->AddRef();	\
	return S_OK;	\
	}	\

#define STDCOM_INTERFACE_BASECLASS_ENTRY_(icast, iface)	\
	if(_uuidof(iface) == riid)	\
	{	\
	*ppv = static_cast<iface*>(static_cast<icast*>(this));	\
	this->AddRef();	\
	return S_OK;	\
	}	\


#define STDCOM_ADDREF \
	std_method_(ULONG, AddRef)(){_atomic_add(&this->m_Ref);return this->m_Ref.value;}

#define STDCOM_RELEASE \
	std_method_(ULONG, Release)(){_atomic_del(&this->m_Ref); if(this->m_Ref.value){return this->m_Ref.value;}else {delete this;}return 0;}

#define END_STDCOM_MAP	return E_NOINTERFACE; }	STDCOM_ADDREF STDCOM_RELEASE


#endif
